/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Actor;

import Actor.enemies.Henchman;
import Actor.enemies.RobotBoss;
import Actor.weapons.Grenade;
import Actor.weapons.LaserRifle;
import Actor.weapons.Semtex;
import Actor.weapons.TargetedMissileLauncher;
import actor.weapons.Explosion;
import actor.weapons.RPG;
import actor.weapons.Weapon;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.vecmath.Point2d;
import projectshanghai.GamePanel;
import projectshanghai.World;

/**
 *
 * @author Eric-Standard
 */
public class Player extends Actor implements KeyListener, MouseListener,
        MouseMotionListener, TeamActor {

    //Pixels per second
    public static final double DEFAULT_MOVE_SPEED = 200;
    private boolean[] keyArr = new boolean[256];
    private Point mousePoint = new Point();
    private Weapon primary, secondary;
    private int width, height;
    private double health = 100;
    private Rectangle r = new Rectangle();
    private Area area = new Area();
    private Point2d lastPos;
    private boolean rightMousePressed = false;
    private Grenade grenade;
    //Health heal rate
    private static final int healthTimeout = 2000;
    private int healthTime = 0;
    private static final int DEFAULT_HEAL_RATE = 50;

    public Player() {
        pos.x = (Map.Map.TILE_WIDTH * Map.Map.MAP_WIDTH / 2);
        pos.y = 0;
        width = 20;
        height = 20;
        secondary = null;
        r.width = width;
        r.height = height;
    }

    @Override
    public void putSelfInWorld(World world) {
        super.putSelfInWorld(world);
        primary = new LaserRifle(this);
        primary.addAmmo(500);
        secondary = new TargetedMissileLauncher(this);
        secondary.addAmmo(100);
    }

    @Override
    public void act(long dt) {
        if (world.mouseMonitor.getButtonClicked(MouseEvent.BUTTON1)) {
            primary.fire();
        }
        if (primary != null) {
            primary.act(dt);
        }
        if (secondary != null) {
            secondary.act(dt);
        }
        if (health < 100) {
            if (healthTime <= 0) {
                health += DEFAULT_HEAL_RATE * dt / 1000d;
                System.out.println(health);
            } else {
                healthTime -= dt;
            }
        }
        //processKeys();
        updateAngle();
        if (vel.x == 0 && vel.y == 0) {
            return;
        }
        if (!pos.equals(lastPos)) {
            lastPos = (Point2d) pos.clone();
        }
        r.x = (int) pos.x;
        r.y = (int) pos.y;
        area = new Area(r);
        vel.normalize();
        vel.scale(DEFAULT_MOVE_SPEED);
        super.act(dt);
        //Clamp position
        if (pos.x < 0) {
            pos.x = 0;
            vel.x = 0;
        }
        if (pos.y < 0) {
            pos.y = 0;
            vel.y = 0;
        }
        Dimension mapSize = world.getMapSize();
        //Clamp position
        if (pos.x > mapSize.width) {
            pos.x = mapSize.width;
            vel.x = 0;
        }
        if (pos.y > mapSize.height) {
            pos.y = mapSize.height;
            vel.y = 0;
        }
        updateAngle();
        world.cam.y = pos.y - GamePanel.PANEL_HEIGHT / 2;
    }

    public void processKeys() {
        vel.x = vel.y = 0;
        ArrayList<Integer> pressedKeys = world.keyMonitor.getPressedKeys();
        for (Integer key : pressedKeys) {
            int keyCode = key.intValue();
            switch (keyCode) {
                case KeyEvent.VK_UP:
                case KeyEvent.VK_W:
                    vel.y = -DEFAULT_MOVE_SPEED;
                    break;
                case KeyEvent.VK_DOWN:
                case KeyEvent.VK_S:
                    vel.y = DEFAULT_MOVE_SPEED;
                    break;
                case KeyEvent.VK_LEFT:
                case KeyEvent.VK_A:
                    vel.x = -DEFAULT_MOVE_SPEED;
                    break;
                case KeyEvent.VK_RIGHT:
                case KeyEvent.VK_D:
                    vel.x = DEFAULT_MOVE_SPEED;
                    break;
                case KeyEvent.VK_F:
                    break;
                case KeyEvent.VK_R:
                    primary.reload();
                    break;
                case KeyEvent.VK_Q:
                    Weapon temp = primary;
                    primary = secondary;
                    secondary = temp;
                    break;
                case KeyEvent.VK_Y:
                    world.add(new RobotBoss());
                    break;
                case KeyEvent.VK_T:
                    world.add(new Henchman());
                    Dimension mapSize = world.getMapSize();
                    for (int i = 0; i < 5; i++) {
                        Henchman henchman = new Henchman();
                        henchman.setPos(new Point2d(world.rand.nextDouble() * mapSize.width, world.rand.nextDouble() * mapSize.height));
                        world.add(henchman);
                    }
                    break;
                default:
                    for (int i = 0; i < 10; i++) {
                        world.add(new Henchman());
                    }
                    break;
            }
        }
    }

    @Override
    public void draw(Graphics g) {
        Graphics2D gr = (Graphics2D) g;
        gr.setColor(Color.WHITE);
        //gr.rotate(angle, (int) pos.x, (int) pos.y);
        gr.fillRect((int) pos.x, (int) pos.y, 20, 20);
        gr.setColor(Color.BLACK);
        gr.drawLine((int) pos.x, (int) pos.y, (int) pos.x + 5, (int) pos.y + 5);
        if (primary != null) {
            primary.draw(g);
        }
    }

    @Override
    public void collide(TileObject tileObject) {
        System.out.println("collide");
        //Prevent the player from going into the Shape
        vel.x = 0;
        vel.x = 0;
        pos = (Point2d) lastPos.clone();
    }

    @Override
    public void collide(Actor a) {
        if (a instanceof Explosion) {
            this.health -= ((Explosion) a).getDamage(this);
            BulletHitMarker b = new BulletHitMarker(a.getPos());
            b.setDrawTime(5000);
            world.add(b);
            healthTime = healthTimeout;
        } else if (a instanceof Projectile) {
            this.health -= ((Projectile) a).getDamage();
            if (((Projectile) a).getDamage() != 0) {
                BulletHitMarker b = new BulletHitMarker(a.getPos());
                b.setDrawTime(5000);
                world.add(b);
                healthTime = healthTimeout;
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (primary == null) {
            primary = new LaserRifle(this);
            primary.setOwner(this);
            primary.addAmmo(500);
            //primary.putSelfInWorld(world);
            secondary = new RPG(this);
            secondary.addAmmo(100);
            //secondary.putSelfInWorld(world);
        }
        int keyCode = e.getKeyCode();
        if (keyCode > 255 || keyArr[keyCode]) {
            return;
        }
        keyArr[keyCode] = true;
        switch (keyCode) {
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:
                vel.y = -DEFAULT_MOVE_SPEED;
                break;
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:
                vel.y = DEFAULT_MOVE_SPEED;
                break;
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_A:
                vel.x = -DEFAULT_MOVE_SPEED;
                break;
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_D:
                vel.x = DEFAULT_MOVE_SPEED;
                break;
            case KeyEvent.VK_F:
                break;
            case KeyEvent.VK_R:
                primary.reload();
                break;
            case KeyEvent.VK_Q:
                Weapon temp = primary;
                primary = secondary;
                secondary = temp;
                break;
            case KeyEvent.VK_Y:
                world.add(new RobotBoss());
                break;
            case KeyEvent.VK_T:
                world.add(new Henchman());
                Dimension mapSize = world.getMapSize();
                for (int i = 0; i < 5; i++) {
                    Henchman henchman = new Henchman();
                    henchman.setPos(new Point2d(world.rand.nextDouble() * mapSize.width, world.rand.nextDouble() * mapSize.height));
                    world.add(henchman);
                }
                break;
            default:
                for (int i = 0; i < 10; i++) {
                    world.add(new Henchman());
                }
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        keyArr[keyCode] = false;
        switch (keyCode) {
            case KeyEvent.VK_UP:
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_W:
            case KeyEvent.VK_S:
                vel.y = 0;
                break;
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_A:
            case KeyEvent.VK_D:
                vel.x = 0;
                break;
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON3) {
            Point2d p = normalizeMousePoint();
            rightMousePressed = true;
            grenade = new Semtex();
            grenade.setOwner(this);
            grenade.setPos(pos);
            grenade.setFuseTime(5000);
            world.add(grenade);
        } else {
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (rightMousePressed && e.getButton() == MouseEvent.BUTTON3) {
            Point2d p = normalizeMousePoint();
            grenade.setPos(new Point2d(pos));
            grenade.setDestination(new Point2d(p.x, p.y));
            grenade = null;
        } else {
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        mousePoint = e.getPoint();
        updateAngle();
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
        updateAngle();
    }

    private void updateAngle() {
        mousePoint = world.mouseMonitor.getPoint();
        double y = mousePoint.y + world.cam.y - pos.y - World.HUD_HEIGHT;
        double x = mousePoint.x + world.cam.x - pos.x - World.HUD_WIDTH;
        angle = Math.atan2(y, x);
    }

    private Point2d normalizeMousePoint() {
        Point2d p = new Point2d();
        p.y = mousePoint.y + world.cam.y - World.HUD_HEIGHT;
        p.x = mousePoint.x + world.cam.x - World.HUD_WIDTH;
        return p;
    }

    @Override
    public Rectangle2D getBoundingRectangle() {
        return r;
    }

    public double getHealth() {
        return health;
    }

    public void drawHUD(Graphics g) {
        //Health bar
        g.setColor(Color.RED);
        g.fillRect(world.getSize().width / 2, 0, (int) (health / 100.0 * world.getSize().width / 2.0), 20);
        //Weapon info
        if (primary != null) {
            primary.drawHUD(g);
        }
    }

    @Override
    public int getTeam() {
        return Team.PLAYER;
    }

    @Override
    public Area getArea() {
        return area;
    }
}
